package com.jike.jkgame;

import java.io.IOException;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.BitmapDrawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.sax.StartElementListener;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.RatingBar;
import android.widget.TextView;

import com.jike.jkgame.data.General;
import com.jike.jkgame.data.MiscDataHelper;
import com.jike.jkgame.data.ResourceType;
import com.jike.jkgame.data.UserResource;
import com.jike.jkgame.db.ResourcesDAO;
import com.jike.jkgame.db.UserDAO;
import com.jike.jkgame.exception.EncodingException;
import com.jike.jkgame.exception.NetworkErrorException;
import com.jike.jkgame.network.MessageFactory;
import com.jike.jkgame.network.NetworkUtilis;
import com.jike.jkgame.network.ServerConfig;
import com.jike.jkgame.network.data.LineupCastResultData;
import com.jike.jkgame.network.data.LineupCastResultData.Cast;
import com.jike.jkgame.widget.CoverFlow;

public class LineupFragment extends Fragment implements OnClickListener {

	private static final long UPDATE_DELAY = 1000;
	
	private CoverFlow mCoverFlow;
	private CoverAdapter mCoverAdapter;
	private ProgressBar mConectingPb;
	private ImageView mArmorIv;
	private ImageView mWeaponIv;
	private ImageView mMountIv;
	private ImageView mTreasureIv;
	private OnCoverItemSelectListener mItemSelectListener;
	private Handler mHandler = new Handler();
	private GeneralViewsHolder mGerneralViews;
	
	private TextView mArmyAttackTv;
	private TextView mArmyDefenseTv;
	private UserResource mSelectRes = null;

	private LineupCastResultData.Cast[] mCasts;
	private int mCurCastIdx;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

	}

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		View v = inflater.inflate(R.layout.lineup_layout, container, false);
		mCoverFlow = (CoverFlow) v.findViewById(R.id.cf_roles);

		mConectingPb = (ProgressBar) v.findViewById(R.id.pb_conecting);
		
		mArmyAttackTv = (TextView) v.findViewById(R.id.tv_attack);
		mArmyDefenseTv = (TextView) v.findViewById(R.id.tv_defense);
		
		mArmorIv = (ImageView) v.findViewById(R.id.iv_armor);
		mWeaponIv = (ImageView) v.findViewById(R.id.iv_weapon);
		mMountIv = (ImageView) v.findViewById(R.id.iv_mount);
		mTreasureIv = (ImageView) v.findViewById(R.id.iv_treasure);
		
		mArmorIv.setOnClickListener(this);
		mWeaponIv.setOnClickListener(this);
		mMountIv.setOnClickListener(this);
		mTreasureIv.setOnClickListener(this);
		
		mGerneralViews = new GeneralViewsHolder();
		mGerneralViews.flagIv = (ImageView) v.findViewById(R.id.iv_flag);
		mGerneralViews.nameTv = (TextView) v.findViewById(R.id.tv_name);
		mGerneralViews.startRb = (RatingBar) v.findViewById(R.id.rb_starts);
		mGerneralViews.levelTv = (TextView) v.findViewById(R.id.tv_level);
		mGerneralViews.expPb = (ProgressBar) v.findViewById(R.id.pb_role_level);
		mGerneralViews.attackTv = (TextView) v.findViewById(R.id.tv_role_attack);
		mGerneralViews.defenseTv = (TextView) v.findViewById(R.id.tv_role_defense);

		mCoverAdapter = new CoverAdapter(this.getActivity());

		// coverImageAdapter.createReflectedImages();

		mCoverFlow.setAdapter(mCoverAdapter);
		mItemSelectListener = new OnCoverItemSelectListener();
		mCoverFlow.setOnItemSelectedListener(mItemSelectListener);
		mCoverFlow.setOnItemClickListener(new OnItemClickListener() {

			@Override
			public void onItemClick(AdapterView<?> parent, View view,
					int position, long id) {
				if (position == getCastCount()) {
					gotoRelaceResource(ResourceType.General);
				}
			}

		});
		mCoverFlow.setSpacing(-25);
		mCoverFlow.setSelection(0, true);
		mCoverFlow.setAnimationDuration(1000);

		v.findViewById(R.id.btn_replace).setOnClickListener(this);

		getLineupInfo();
		
		return v;
	}
	
	private void gotoRelaceResource(ResourceType type) {
		Intent intent = null;
		if (type == ResourceType.General) {
			intent = new Intent(getActivity(), SelectResourcesActicity.class);
		} else {
			intent = new Intent(getActivity(), ShowResourceActivity.class);
		}
		intent.putExtra(Global.Keys.RES_TYPE, type);

		startActivityForResult(intent, 1000);
	}
	
	private Cast getCurrentCast() {
		if (mCasts != null && mCasts.length > mCurCastIdx && mCurCastIdx > 0) {
			return mCasts[mCurCastIdx];
		}
		return null;
	}

	@Override
	public void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);

		if (requestCode == 1000 && resultCode == Activity.RESULT_OK) {
			mSelectRes = (UserResource) data.getSerializableExtra(Global.Keys.RES_DATA);
			if (mSelectRes != null) {
				ChangeResourceTask task = new ChangeResourceTask();
				ChangeResourceParams param = new ChangeResourceParams();
				param.castIdx = mCurCastIdx;
				param.type = mSelectRes.res.ordinal() + 1;
				param.sid = mSelectRes.sid;
				task.execute(param);
			}
		}

	}

	public class OnCoverItemSelectListener implements OnItemSelectedListener {
		@Override
		public void onItemSelected(AdapterView<?> parent, View view,
				final int postion, long id) {
			mHandler.removeCallbacksAndMessages(null);
			mHandler.postDelayed(new Runnable() {
				
				@Override
				public void run() {
					updateCast(postion);
					
				}
			},  UPDATE_DELAY);
		
		}

		@Override
		public void onNothingSelected(AdapterView<?> parent) {

		}
	}
	
	private void updateCast(int idx) {
		mCurCastIdx = idx;
		Cast cast = mCasts[idx];
		
		ResourcesDAO resDao = ResourcesDAO.get();
		if (cast != null) {
			UserResource general = cast.general;
			General gen = resDao.getGeneral(general.tid);
			mGerneralViews.nameTv.setText(gen.name);
			mGerneralViews.levelTv.setText("LV" + general.level);
			mGerneralViews.startRb.setRating(general.star);
			mGerneralViews.expPb.setProgress(general.exp);
			mGerneralViews.attackTv.setText(String.valueOf(general.attack));
			mGerneralViews.defenseTv.setText(String.valueOf(general.defense));
			// TODO 更新对应武将的资源：武器、防具等
		} else {
			mGerneralViews.reset();
		}
	}

	private int getCastCount() {
		if (mCasts == null) {
			return 0;
		} else {
			return mCasts.length;
		}
	}
	
	public static class GeneralViewsHolder {
		public ImageView flagIv;
		public TextView nameTv;
		public TextView levelTv;
		public RatingBar startRb;
		public ProgressBar expPb;
		public TextView attackTv;
		public TextView defenseTv;
		
		public void reset() {
			flagIv.setImageResource(R.drawable.ic_flag);
			nameTv.setText("Name");
			levelTv.setText("LV0");
			startRb.setRating(0);
			expPb.setProgress(0);
			attackTv.setText("0");
			defenseTv.setTag("0");
		}
	}
	
	public class CoverAdapter extends BaseAdapter {
		int mGalleryItemBackground;
		private Context mContext;

		public CoverAdapter(Context c) {
			mContext = c;
		}

		public int getCount() {
			return getCastCount();
		}

		public Object getItem(int position) {
			return position;
		}

		public long getItemId(int position) {
			return position;
		}

		public View getView(int position, View convertView, ViewGroup parent) {

			// Use this code if you want to load from resources
			ImageView i = new ImageView(mContext);

			if (position == getCastCount()) {
				i.setImageResource(R.drawable.ic_launcher);
			} else {
				i.setImageResource(R.drawable.general);
			}

			i.setLayoutParams(new CoverFlow.LayoutParams(
					CoverFlow.LayoutParams.WRAP_CONTENT, 300));
			i.setScaleType(ImageView.ScaleType.CENTER_INSIDE);

			// Make sure we set anti-aliasing otherwise we get jaggies
			BitmapDrawable drawable = (BitmapDrawable) i.getDrawable();
			drawable.setAntiAlias(true);
			return i;

		}

		/**
		 * Returns the size (0.0f to 1.0f) of the views depending on the
		 * 'offset' to the center.
		 */
		public float getScale(boolean focused, int offset) {
			/* Formula: 1 / (2 ^ offset) */
			return Math.max(0, 1.0f / (float) Math.pow(2, Math.abs(offset)));
		}

	}
	
	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.btn_replace:
			gotoRelaceResource(ResourceType.General);
			break;
		case R.id.iv_armor:
			gotoRelaceResource(ResourceType.Armor);
			break;
		case R.id.iv_weapon:
			gotoRelaceResource(ResourceType.Weapon);
			break;
		case R.id.iv_mount:
			gotoRelaceResource(ResourceType.Mount);
			break;
		case R.id.iv_treasure:
			gotoRelaceResource(ResourceType.Treasure);
			break;
		default:
			break;
		}
	}

	private void getLineupInfo() {
		GetLineupInfoTask task = new GetLineupInfoTask();

		task.execute(null);
	}
	
	class GetLineupInfoTask extends
			AsyncTask<Object, Integer, LineupCastResultData> {

		@Override
		protected LineupCastResultData doInBackground(Object... params) {

			JSONObject req = MessageFactory.createGetLineupInfoReqMessage();
			LineupCastResultData result = null;
			try {
				String response = NetworkUtilis.getHttpString(ServerConfig
						.get().getGameServer(), req);
				JSONObject json = new JSONObject(response);
				result = new LineupCastResultData();
				result.opcode = json.optInt("opcode");

				if (result.opcode == 0) {
					JSONArray casts = json.getJSONArray("cast");

					MiscDataHelper helper = MiscDataHelper.get();
					result.cast = new LineupCastResultData.Cast[helper.getTeamUpper()];
					int size = casts.length();
					UserDAO dao = UserDAO.get();
					for (int i = 0; i < size; ++i) {
						JSONObject castObj = casts.getJSONObject(i);
						LineupCastResultData.Cast cast = new LineupCastResultData.Cast();
						int idx = castObj.optInt("idx");
						JSONObject resObj = castObj.optJSONObject("general");
						cast.general = UserResource.fromJSON(ResourceType.General, resObj);
						dao.insertOrReplaceUserResource(cast.general);
						
						resObj = castObj.optJSONObject("weapon");
						cast.weapon = UserResource.fromJSON(ResourceType.Weapon, resObj);
						dao.insertOrReplaceUserResource(cast.weapon);
						
						resObj = castObj.optJSONObject("armor");
						cast.armor = UserResource.fromJSON(ResourceType.Armor, resObj);
						dao.insertOrReplaceUserResource(cast.armor);
						
						resObj = castObj.optJSONObject("mount");
						cast.mount = UserResource.fromJSON(ResourceType.Mount, resObj);
						dao.insertOrReplaceUserResource(cast.mount);
						
						resObj = castObj.optJSONObject("treasure");
						cast.treasure = UserResource.fromJSON(ResourceType.Treasure, resObj);
						dao.insertOrReplaceUserResource(cast.treasure);
						
						result.cast[idx-1] = cast;
						
					}

					result.army_att_min = json.optInt("army_att_min");
					result.army_att_max= json.optInt("army_att_max");
					result.army_def_min = json.optInt("army_def_min");
					result.army_def_max = json.optInt("army_def_max");
				}

			} catch (NetworkErrorException e) {
				e.printStackTrace();
			} catch (EncodingException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			} catch (JSONException e) {
				e.printStackTrace();
			}

			return result;
		}

		@Override
		protected void onPostExecute(LineupCastResultData result) {
			super.onPostExecute(result);
			mConectingPb.setVisibility(View.GONE);
			if (result != null && result.opcode == 0) {
				mArmyAttackTv.setText(String.format("%d~%d", result.army_att_min, result.army_att_max));
				mArmyDefenseTv.setText(String.format("%d~%d", result.army_def_min, result.army_def_max));
				mCasts = result.cast;
				mCoverAdapter.notifyDataSetChanged();
			}
		}

		@Override
		protected void onPreExecute() {
			super.onPreExecute();
			mConectingPb.setVisibility(View.VISIBLE);
		}

	}
	
	class ChangeResourceTask extends AsyncTask<ChangeResourceParams, Object, Integer> {

		@Override
		protected Integer doInBackground(ChangeResourceParams... params) {
			if (params == null || params.length == 0) {
				return null;
			}
			ChangeResourceParams param = params[0];
			JSONObject req = MessageFactory.createChangeResourceReqMessage(param.castIdx, param.type, param.sid);
			
			try {
				String response = NetworkUtilis.getHttpString(ServerConfig.get().getGameServer(), req);
				JSONObject json = new JSONObject(response);
				return json.optInt("opcode", -1);
				
			} catch (NetworkErrorException e) {
				e.printStackTrace();
			} catch (EncodingException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			} catch (JSONException e) {
				e.printStackTrace();
			}

			return null;
		}

		@Override
		protected void onPostExecute(Integer result) {
			super.onPostExecute(result);
			mConectingPb.setVisibility(View.GONE);
			if (result != null && result == 0) {
				if (getCurrentCast() == null) {
					mCasts[mCurCastIdx] = new Cast();
					mCasts[mCurCastIdx].idx = mCurCastIdx;
				}
				mCasts[mCurCastIdx].setResource(mSelectRes);
				mCoverAdapter.notifyDataSetChanged();
			}
		}

		@Override
		protected void onPreExecute() {
			super.onPreExecute();
			mConectingPb.setVisibility(View.VISIBLE);
		}
		
	}
}

class ChangeResourceParams {
	public int castIdx;
	public int type;
	public int sid;
}
